package com.soap.desensitize.strategy.rreversible.symmetry;

import com.soap.desensitize.encry.rreversible.symmetry.AbstractSymmetryEncry;
import com.soap.desensitize.exception.strategy.DecodeException;
import com.soap.desensitize.exception.strategy.EncodeException;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Key;
import java.util.Base64;

/**
 * @desc：   3des加密
 * @author： QGP
 * @create： 2022/4/24 15:48
 */
public class ThreeDesStrategy extends AbstractSymmetryEncry<String> {
    private static ThreeDesStrategy instance = null;

    /**
     * @desc  获得实例
     * @return
     */
    public static synchronized ThreeDesStrategy getInstance(){
        if(instance == null){
            instance = new ThreeDesStrategy();
        }
        return instance;
    }

    /**
     * @desc  需要16位 密码
     */
    private String password="111111111111111111111111";

    /**
     * 偏移变量，固定占8位字节
     */
    private final static String IV_PARAMETER = "javaplus";

    /**
     * 默认编码
     */
    private static final String CHARSET = "utf-8";

    /**
     * @desc 默认使用子类加密密码
     */
    private ThreeDesStrategy(){
        super.password=this.password;
    }

    /**
     * @desc  3des加密
     * @param password   密码
     * @param data       数据
     * @return
     */
    @Override
    public  String encode(String password, String data) throws EncodeException {
        try {
            Key deskey = null;
            DESedeKeySpec spec = new DESedeKeySpec(password.getBytes());
            SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
            deskey = keyfactory.generateSecret(spec);

            Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
            IvParameterSpec ips = new IvParameterSpec(IV_PARAMETER.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
            byte[] encryptData = cipher.doFinal(data.getBytes(CHARSET));
            return new String(Base64.getEncoder().encode(encryptData));
        } catch (Exception e) {
            throw new EncodeException("加密异常");
        }
    }

    /**
     * @desc  3des解密
     * @param password   密码
     * @param data       解密数据
     * @return
     */
    @Override
    public  String decode(String password, String data) throws DecodeException {
        try {
            Key deskey = null;
            DESedeKeySpec spec = new DESedeKeySpec(password.getBytes());
            SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
            deskey = keyfactory.generateSecret(spec);
            Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
            IvParameterSpec ips = new IvParameterSpec(IV_PARAMETER.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
            byte[] decryptData = cipher.doFinal(Base64.getDecoder().decode(data));
            return new String(decryptData, CHARSET);
        } catch (Exception e) {
            throw new DecodeException("解密异常");
        }
    }


    /**
     * @desc 使用默认加密密码，加密
     */
    @Override
    public String encode(String data) throws EncodeException {
        if (getPassword()!=null){
            return encode(getPassword(), data);
        }
        return encode(password, data);
    }

    /**
     * @desc 使用默认加密密码，解密
     */
    @Override
    public String decode(String data) throws DecodeException {
        if (getPassword()!=null){
            return decode(getPassword(), data);
        }
        return decode(password, data);
    }
}
